﻿// <copyright file="EasyWebApp.cs" company="<Customer Name>">This is a "work-for-hire". or Copyright (C) 2010 MicroCODE Incorporated Troy, MI</copyright><author><Class Author's Name></author>

/*
 *      Title:    <Class Description>
 *      Module:   ClassTemplate (<Namespace>:ClassTemplate.cs)
 *      Project:  <Project Name>
 *      Customer: <Customer Name>
 *      Facility: MicroCODE Incorporated
 *      Date:     <Class Creation Date>
 *      Author:   <Class Author's Name>
 * 
 * 
 * 
 *  
 *      MODIFICATIONS:
 *      --------------
 *
 *  Date:         By-Group:   Rev:     Description:
 *
 *  DD-Mmm-YYYY   XYZ-GROUP  {0001}    Describe reason for creating or modifying class... 
 * 
 * 
 * 
 */
using System;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Text;
using Org.EasyWeb.Cache;
using Org.EasyWeb.Provider;
using Org.EasyWeb.Sys;
using Org.EasyWeb.SysUtil;

namespace Org.EasyWeb.Data
{
    public class AutoGenerateXmlTable : ICacheItem, IDisposable
    {
        private StringBuilder fDataXml;
        private StringBuilder fItemXml;
        private string fXmlContent;

        private const string UICONTROLTEMPLATE = "<zj:ValidateBox><zj:Required>{0}</zj:Required><zj:ValidType>{1}</zj:ValidType></zj:ValidateBox>";

        public string Execute(DataSet data)
        {
            CreateCodeEventArgs e = new CreateCodeEventArgs();
                    
            DataRelation relation = data.Relations[0];
            DataTable table = data.Tables["DD_TABLE"];
            foreach (DataRow row in table.Rows)
            {
                if (row["DT_TABLE_CHAR"].ToString() != "01")
                    continue;
                if (row["DT_TABLE_USED"].ToString() != "1")
                    continue;
                string name = StringUtil.GetFileName(row["DT_TABLE_NAME"].ToString());

                DataRow[] childRows = row.GetChildRows(relation);

                e.SetProperties(name, row, childRows);

                return fXmlContent = GenerateXml(e);
            }
            return string.Empty;
        }

        public DataSet NewFile()
        {
            DataSet ds = new DataSet();
            string xml = EasyWebResUtil.GetResourceString("TableSchema");
            StringReader reader = new StringReader(xml);
            ds.ReadXml(reader);
            return ds;
        }

        public string GenerateTableFromSchema(string tableName)
        {
            DataSet ds = NewFile();
            DataTable tableInfo = ds.Tables["DD_TABLE"];
            DataTable fieldInfo = ds.Tables["DD_FIELD_INFO"];

            DataTable table = GetTableStructure(tableName, GlobalProvider.Connection);

            DataRow tableRow = tableInfo.NewRow();
            tableRow.BeginEdit();
            tableRow["DT_TABLE_NAME"] = tableRow["DT_TABLE_DESC"] = tableName;
            tableRow["DT_TABLE_CHAR"] = tableName.ToUpper().StartsWith("CD_") ? "02" : "01";
            tableRow.EndEdit();
            tableInfo.Rows.Add(tableRow);

            int i = 0;
            foreach (DataColumn column in table.Columns)
            {
                string columnName = column.ColumnName;
                DataRow fieldRow = fieldInfo.NewRow();
                fieldRow.BeginEdit();
                fieldRow["DF_TABLE_NAME"] = tableName;
                fieldRow["DF_FIELD_NAME"] = fieldRow["DF_FIELD_DESC"] = columnName;
                int length = column.MaxLength;
                if (length == -1)
                    length = 0;

                string type = column.DataType.ToString();
                switch (type)
                {
                    case "System.Byte":
                    case "System.SByte":
                    case "System.Int32":
                    case "System.Int16":
                    case "System.Int64":
                    case "System.UInt32":
                    case "System.UInt16":
                    case "System.UInt64":
                        type = "int";
                        break;
                    case "System.DateTime":
                        type = "Date";
                        break;
                    case "System.TimeSpan":
                        type = "DateTime";
                        break;
                    case "System.Double":
                    case "System.Single":
                    case "System.Decimal":
                        type = "double";
                        break;
                    case "System.String":
                    case "System.Char":
                        type = (length == int.MaxValue) ? "text" : "string";
                        break;
                    case "System.Byte[]":
                        type = "blob";
                        break;
                    default:
                        type = "string";
                        break;
                }

                fieldRow["DF_DATA_TYPE"] = type;
                bool isKey = IsKey(table, columnName);
                fieldRow["DF_IS_KEY"] = isKey;
                fieldRow["DF_LENGTH"] = (type == "string") ? length : 0;
                fieldRow["DF_IS_EMPTY"] = column.AllowDBNull;
                fieldRow["DF_IS_TWO_COLUMN"] = (type == "text") ? "one" : "three";
                string ctrl = (isKey) ? "Hidden" : "Text";
                if (type == "text")
                    ctrl = "TextArea";
                fieldRow["DF_HTML_CTRL"] = ctrl;
                fieldRow["DF_ORDER"] = (++i) * 10;
                fieldRow["DF_DEFAULT_VALUE"] = column.DefaultValue;
                bool isUsed = columnName.IndexOf("UNUSED") != -1;
                bool isCrtUpd = columnName.EndsWith("OWNER_ID") || columnName.EndsWith("CREATE_ID")
                    || columnName.EndsWith("CREATE_DATE") || columnName.EndsWith("UPDATE_ID")
                    || columnName.EndsWith("UPDATE_DATE");
                fieldRow["DF_IS_INSERT"] = fieldRow["DF_IS_UPDATE"] = !(isUsed || isCrtUpd);
                fieldRow["DF_IS_DETAIL"] = !isUsed;
                //fieldRow["DF_IS_LIST"] = !(isUsed || isCrtUpd || ctrl == "Hidden" || type == "text");
                //jin zhao
                fieldRow["DF_IS_LIST"] = !(isUsed || isCrtUpd || type == "text");
                fieldRow.EndEdit();
                fieldInfo.Rows.Add(fieldRow);
            }

            ds.AcceptChanges();

            return Execute(ds);
        }

        public string GenerateXml(CreateCodeEventArgs e)
        {
            fDataXml = new StringBuilder(10240);
            fItemXml = new StringBuilder(1024);

            fDataXml.Remove(0, fDataXml.Length);
            fDataXml.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n");
            fDataXml.Append("<Toolkit version=\"2.0\" xsi:noNamespaceSchemaLocation=\"../../DTD2/Data.xsd\" xmlns:zj=\"http://www.zju.edu.cn\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n");
            fDataXml.AppendFormat("  <zj:Table TableName=\"{0}\" TableDesc=\"{1}\">\r\n",
                e.TableRow["DT_TABLE_NAME"], e.TableRow["DT_TABLE_DESC"]);
            foreach (DataRow row in e.FieldRows)
            {
                fDataXml.Append(GetXml(row));
            }
            fDataXml.Append("  </zj:Table>\r\n");
            fDataXml.Append("</Toolkit>\r\n");

            return fDataXml.ToString();
        }

        private string listHref;

        private string GetXml(DataRow row)
        {
            fItemXml.Remove(0, fItemXml.Length);
            string htmlCtrl = row["DF_HTML_CTRL"].ToString();
            string fieldName = row["DF_FIELD_NAME"].ToString();
            fItemXml.AppendFormat("    <zj:Field DataType=\"{0}\"", row["DF_DATA_TYPE"]);
            if (row["DF_IS_KEY"].ToString().ToLower() == "true")
                fItemXml.Append(" IsKey=\"true\" ");
            bool IsRequired = false;
            if (row["DF_IS_EMPTY"].ToString().ToLower() == "true")
            {
                fItemXml.Append(" IsEmpty=\"true\"");
            }
            else 
            {
                IsRequired = true;
            }
        

            //自动添加USER　ＥＡＳＹＳＥＡＲＣＨ
            string userEasySearch = string.Empty;
            if (fieldName.IndexOf("CREATE_ID") != -1 || fieldName.IndexOf("UPDATE_ID") != -1)
            {
                userEasySearch = "      <zj:EasySearch RegName=\"USER\"/>\r\n";
            }

            fItemXml.Append(">\r\n");
            fItemXml.AppendFormat("      <zj:FieldName>{0}</zj:FieldName>\r\n", fieldName);
            fItemXml.AppendFormat("      <zj:DisplayName>{0}</zj:DisplayName>\r\n", row["DF_FIELD_DESC"]);

            if (row["DF_LENGTH"].ToString() != "0")
                fItemXml.AppendFormat("      <zj:Length>{0}</zj:Length>\r\n", row["DF_LENGTH"]);
            if (row["DF_CODE_TABLE"].ToString() != string.Empty)
                fItemXml.AppendFormat("      <zj:CodeTable>{0}</zj:CodeTable>\r\n", row["DF_CODE_TABLE"]);

            string temp = string.Empty;
            string extension = row["DF_EXTENSION"].ToString();
            if (htmlCtrl == "EasySearch" && extension != string.Empty)
                fItemXml.AppendFormat("      <zj:EasySearch RegName=\"{0}\"/>", extension);
            else if (userEasySearch != string.Empty)
            {
                fItemXml.Append(userEasySearch);

            }

            temp = " ThreeColumn=\"" + row["DF_IS_TWO_COLUMN"].ToString() + "\"";
            if (row["DF_DATA_TYPE"].ToString() == "double" && extension != string.Empty)
                temp += string.Format(" Format=\"{0}\"", row["DF_EXTENSION"]);

            bool bIsInsert = row["DF_IS_INSERT"].ToString().ToLower() == "true" ? true : false;
            bool bIsUpdate = row["DF_IS_UPDATE"].ToString().ToLower() == "true" ? true : false;
            bool bIsList = row["DF_IS_LIST"].ToString().ToLower() == "true" ? true : false;
            bool bIsDetail = row["DF_IS_DETAIL"].ToString().ToLower() == "true" ? true : false;
            string strDefaultShow = string.Empty;
            if (bIsDetail && bIsInsert && bIsList && bIsUpdate)
                strDefaultShow = "DefaultShow=\"All\" ";
            else if (!bIsDetail && !bIsInsert && !bIsList && !bIsUpdate)
                strDefaultShow = "DefaultShow=\"None\" ";
            else if (bIsDetail && bIsInsert && !bIsList && bIsUpdate)
                strDefaultShow = "DefaultShow=\"AllNoList\" ";
            else if (bIsDetail && !bIsInsert && !bIsList && !bIsUpdate)
                strDefaultShow = "DefaultShow=\"Detail\" ";
            else
            {
                //Insert|Update|List|Detail
                string strPatter = string.Empty;
                if (bIsInsert)
                {
                    strPatter = " Insert";
                }
                if (bIsUpdate)
                {
                    if (strPatter == string.Empty)
                    {
                        strPatter = " Update";
                    }
                    else
                    {
                        strPatter += " | Update";
                    }
                }
                if (bIsList)
                {
                    if (strPatter == string.Empty)
                    {
                        strPatter = " List";
                    }
                    else
                    {
                        strPatter += " | List";
                    }
                }
                if (bIsDetail)
                {
                    if (strPatter == string.Empty)
                    {
                        strPatter = " Detail";
                    }
                    else
                    {
                        strPatter += " | Detail";
                    }
                }
                strDefaultShow = string.Format("DefaultShow=\"{0}\" ", strPatter);
            }


            if (temp != string.Empty)
            {
                if (string.IsNullOrEmpty(listHref) && htmlCtrl.ToLower() != "hidden")
                {
                    listHref = "ListRef=\"true\"";
                    fItemXml.AppendFormat("      <zj:Display{0} {1} {2}/>\r\n", temp, strDefaultShow, listHref); 
                }
                else
                {
                    fItemXml.AppendFormat("      <zj:Display{0} {1} {2}/>\r\n", temp, strDefaultShow, ""); 
                }            
            }


            temp = string.Empty;
            string dataType = row["DF_DATA_TYPE"].ToString().ToLower();

            if (dataType == "date" || dataType == "datetime" || extension == "datespan")
                temp = " Span=\"true\"";
            if (htmlCtrl == "CheckBox")
                temp = " CheckValue=\"1\"";

            if (dataType == "string" || dataType == "date" || dataType == "datetime")
            {
                if (temp == string.Empty)
                {
                    temp = " Search=\"title\" ";
                }
                else
                {
                    temp += " Search=\"title\" ";
                }
            }
            if (temp != string.Empty)
                fItemXml.AppendFormat("      <zj:Extension{0}/>\r\n", temp);
           
            int firstIndex = 0;
            if (IsRequired)
            {
                firstIndex = 1;               
            }
            string controlContent = string.Format(UICONTROLTEMPLATE, IsRequired, string.Format("length[{0},{1}]",firstIndex, row["DF_LENGTH"]));
            fItemXml.AppendFormat("      <zj:HtmlCtrl HtmlCtrl=\"{0}\" Order=\"{1}\">{2}</zj:HtmlCtrl>\r\n", htmlCtrl, row["DF_ORDER"], controlContent);


            string defaultValue = string.Empty;
            if (row["DF_DEFAULT_VALUE"].ToString() != string.Empty)
                defaultValue = string.Format(" <zj:DefaultValue NeedParse=\"false\">{0}</zj:DefaultValue>\r\n", row["DF_DEFAULT_VALUE"]);

            fItemXml.Append("    </zj:Field>\r\n");

            return fItemXml.ToString();
        }

        public DataTable GetTableStructure(string tableName, IDbConnection conn)
        {
            string sql = string.Format("SELECT * FROM {0} WHERE 1=0", tableName);
            DataSet ds = new DataSet();
            DbDataAdapter da = (DbDataAdapter)GlobalProvider.DataAdapter;// new SqlDataAdapter(sql, conn);
            da.SelectCommand = (DbCommand)GlobalProvider.Command;
            da.SelectCommand.CommandText = sql;
            da.SelectCommand.Connection = (DbConnection)conn;
            da.SelectCommand.Connection.ConnectionString = AppSettings.Current.ConnectionString;
            da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
            da.Fill(ds, tableName);
            return ds.Tables[tableName];
        }

        private bool IsKey(DataTable table, string columnName)
        {
            foreach (DataColumn col in table.PrimaryKey)
                if (col.ColumnName == columnName)
                    return true;
            return false;
        }

        #region IDisposable Members

        public void Dispose()
        {
           //throw new NotImplementedException();
        }

        #endregion

        #region ICacheItem Members

        public ICacheDependency Dependency
        {
            get { throw new NotImplementedException(); }
        }

        public string Key
        {
            get
            {
                return fXmlContent;
            }
            set
            {
                GenerateTableFromSchema(value);
            }
        }

        #endregion
    }
}
